﻿#include <iostream>
#include <string>
#include <map>
#include <stack>
using namespace std;
/* 类行为型模式
1.意图
给定一个语言，定义它的文法的一个表示，并定义一个解释器，这个解释器使用该表示来解释语言中的句子。
2.适用性
当有一个语言需要解释执行，并且你可将该语言中的句子表示为一个抽象语法树时，可使用解释器模式。而当存在以下情况时该模式效果最好：
a.该文法简单对于复杂文法，文法的类层次变得庞大而无法管理。
b.效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的，而是首先将它们转换成另一种形式。例如，正则表达式
通常被转换成状态机。但即使在这种情况下，转换器仍可用解释器模式实现，该模式仍是有用的。
*/
//抽象表达式
class Expression
{
public:
	//a+b-c
	virtual int Interpreter(map<string, int>& var) = 0;
};
//变量解析器
class VarExpression :public Expression
{
public:
	VarExpression(string key):key(key){}
	int Interpreter(map<string, int>& var)
	{
		return var[key];
	}
private:
	string key;
};
//运算符解析器
//抽象父类
class SymbolExpression :public Expression
{
protected:
	Expression* left;
	Expression* right;
public:
	SymbolExpression(Expression* left,Expression* right):left(left),right(right){}
	//Expression* GetLeft() { return left; }
	//Expression* GetRight() { return right; }
};
//具体子类
class AddExpression :public SymbolExpression
{
public:
	AddExpression(Expression* left,Expression* right):SymbolExpression(left,right){}
	int Interpreter(map<string, int>& var)
	{
		return left->Interpreter(var) + right->Interpreter(var);
	}
};

class SubExpression :public SymbolExpression
{
public:
	SubExpression(Expression* left, Expression* right) :SymbolExpression(left, right) {}
	int Interpreter(map<string, int>& var)
	{
		return left->Interpreter(var) - right->Interpreter(var);
	}
};

//封装调用接口-->解析器的封装类
class Calculator
{
private:
	Expression* expression;
public:
	Calculator(string expstr)
	{
		expression = NULL;
		stack<Expression*> stkexp;
		Expression* left = NULL;
		Expression* right = NULL;
		for (int i = 0; i < expstr.length(); i++)
		{
			switch (expstr[i])
			{
			case '+':
				//从栈中取左操作数
				left = stkexp.top();
				stkexp.pop();
				//从文法字符串取出+后面的右操作数
				right = new VarExpression(expstr.substr(++i, 1));
				//将新的结果存入栈
				stkexp.push(new AddExpression(left, right));
				break;
			case '-':
				//从栈中取左操作数
				left = stkexp.top();
				stkexp.pop();
				//从文法字符串取出+后面的右操作数
				right = new VarExpression(expstr.substr(++i, 1));
				//将新的结果存入栈
				stkexp.push(new SubExpression(left, right));
				break;
			default:
				stkexp.push(new VarExpression(expstr.substr(i, 1)));
				break;
			}
		}
		//栈中保存的就是最终语法数的根
		if (!stkexp.empty())
		{
			expression = stkexp.top();
			stkexp.pop();
		}
	}
	int Run(map<string, int>& var)
	{
		return (expression == NULL) ? 0 : expression->Interpreter(var);
	}
};
/*
int main()
{
	string expstr = "a-b+c";
	map<string, int> var;
	var["a"] = 10;
	var["b"] = 30;
	var["c"] = 20;
	Calculator cal(expstr);
	cout << cal.Run(var) << endl;


	return 0;
}
*/